package controller

import (
	"encoding/base64"
	"path"
	"strconv"

	"device-admin/config"
	"device-admin/config/mysql"
	"device-admin/internal/app/grpc/protoc/robotc"
	"device-admin/internal/app/grpc/service/robot"
	"device-admin/internal/app/web/service/cmd"
	"device-admin/internal/app/web/service/device_map"
	"device-admin/internal/models"
	"device-admin/internal/pkg/file"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/response"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"google.golang.org/protobuf/proto"
)

type Map struct{}

// Detail 地图详细数据
func (Map) Detail(c *gin.Context) {
	var mapDetail struct {
		models.DeviceMap
		MapImage string `json:"map_image" gorm:"-"`
	}
	mysql.NewDB().Model(&models.DeviceMap{}).
		Select(
			"id",
			"robot_id",
			"map_name",
			"map_md5", "map_ex_md5",
			"width", "height", "r11", "r12", "r21", "r22", "tx", "ty",
			"created_at", "updated_at",
		).
		Where("robot_id = ?", c.Query("robot_id")).
		Where("id = ?", c.Query("map_id")).
		Take(&mapDetail)

	// 为了更新兼容，部分地图没有更新时间，导致转换矩阵没上报
	if mapDetail.R11 == 0 &&
		mapDetail.R12 == 0 &&
		mapDetail.R21 == 0 &&
		mapDetail.R22 == 0 &&
		mapDetail.Tx == 0 &&
		mapDetail.Ty == 0 {
		mapEx := &robotc.ReqDDRVLNMapEx{}
		if mapExtData, err := file.ReadMapFile(config.Config.FileSaveDir, path.Join(mapDetail.RobotID, mapDetail.MapExMd5)+".ext"); err == nil {
			proto.Unmarshal(mapExtData, mapEx)
			mapDetail.R11 = mapEx.GetBasedata().GetAffinedata().R11
			mapDetail.R12 = mapEx.GetBasedata().GetAffinedata().R12
			mapDetail.R21 = mapEx.GetBasedata().GetAffinedata().R21
			mapDetail.R22 = mapEx.GetBasedata().GetAffinedata().R22
			mapDetail.Tx = mapEx.GetBasedata().GetAffinedata().Tx
			mapDetail.Ty = mapEx.GetBasedata().GetAffinedata().Ty
		}

	}
	mapDetail.MapImage = "/" + path.Join("file", "device-admin", "device-map", mapDetail.RobotID, mapDetail.MapMd5+".png")
	response.JSON(c, mapDetail, nil)
}

// LatestMap 最近使用的地图
func (Map) LatestMap(c *gin.Context) {
	mapName, mapImg, mapExt, err := device_map.GetLatestMap(c.Query("robot_id"))
	response.JSON(c, map[string]interface{}{
		"map_name": mapName,
		"map_img":  mapImg,
		"map_ext":  mapExt,
	}, err)
}

// MapList 地图列表
func (Map) MapList(c *gin.Context) {
	page, _ := strconv.Atoi(c.Query("page"))
	limit, _ := strconv.Atoi(c.Query("limit"))
	list, total, err := device_map.MapList(c.Query("robot_id"), c.Query("map_name"), page, limit)
	response.JSON(c, gin.H{
		"list":  list,
		"total": total,
	}, err)
}

// SetRunningMap 选择地图
func (Map) SetRunningMap(c *gin.Context) {
	var params struct {
		RobotID string `json:"robot_id"`
		MapName string `json:"map_name"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)

	cmdName := "setRunningMap"
	// 检测繁忙
	if err := cmd.ISBusy(params.RobotID, cmdName, "95"); err != nil {
		response.JSON(c, nil, err)
	}
	var err error
	if helper.CompareVersion("V", c.GetString("device_firmware_version"), "V1.65", "") == 2 {
		err = robot.WildmsgSetRunningMap(params.RobotID, params.MapName, c.GetString("username"))
	} else {
		err = robot.SetRunningMapCMDPack(params.RobotID, params.MapName, c.GetString("username"))
	}
	response.JSON(c, nil, err)
}

// TaskList 任务列表
func (Map) TaskList(c *gin.Context) {
	taskList, err := device_map.TaskList(c.Query("robot_id"), c.Query("map_name"))
	response.JSON(c, taskList, err)
}

// 修改任务次数
func (Map) ModifyTaskTimes(c *gin.Context) {
	var params struct {
		RobotID  string `json:"robot_id"`
		MapName  string `json:"map_name"`
		TaskName string `json:"task_name"`
		RunCount int    `json:"run_count"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	var err error
	if helper.CompareVersion("V", c.GetString("device_firmware_version"), "V1.65", "") == 2 {
		err = robot.WildmsgModifyTaskTimes(params.RobotID, params.MapName, params.TaskName, params.RunCount, c.GetString("username"))
	} else {
		err = robot.ModifyWorkingTimesCMDPack(params.RobotID, params.MapName, params.TaskName, params.RunCount, c.GetString("username"))
	}
	response.JSON(c, nil, err)
}

// 修改任务时段
func (Map) ModifyTaskTime(c *gin.Context) {
	var params struct {
		RobotID   string `json:"robot_id"`
		MapName   string `json:"map_name"`
		TaskName  string `json:"task_name"`
		StartHour int    `json:"start_hour"`
		StartMin  int    `json:"start_min"`
		EndHour   int    `json:"end_hour"`
		EndMin    int    `json:"end_min"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	var err error
	if helper.CompareVersion("V", c.GetString("device_firmware_version"), "V1.65", "") == 2 {
		err = robot.WildmsgModifyTaskTime(params.RobotID, params.MapName, params.TaskName, params.StartHour, params.StartMin, params.EndHour, params.EndMin, c.GetString("username"))
	} else {
		err = robot.ModifyWorkingTimeCMDPack(params.RobotID, params.MapName, params.TaskName, params.StartHour, params.StartMin, params.EndHour, params.EndMin, c.GetString("username"))
	}
	response.JSON(c, nil, err)
}

// DeleteTask 删除任务
func (Map) DeleteTask(c *gin.Context) {
	var params struct {
		RobotID  string `json:"robot_id"`
		MapName  string `json:"map_name"`
		TaskName string `json:"task_name"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	var err error
	if helper.CompareVersion("V", c.GetString("device_firmware_version"), "V1.65", "") == 2 {
		err = robot.WildmsgDeleteTask(params.RobotID, params.MapName, params.TaskName, c.GetString("username"))
	} else {
		err = robot.DeleteTaskCMDPack(params.RobotID, params.MapName, params.TaskName, c.GetString("username"))
	}
	response.JSON(c, nil, err)
}

// DeleteMap 删除地图
func (Map) DeleteMap(c *gin.Context) {
	var params struct {
		RobotID string `json:"robot_id"`
		MapName string `json:"map_name"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	var err error
	if helper.CompareVersion("V", c.GetString("device_firmware_version"), "V1.65", "") == 2 {
		err = robot.WildmsgDeleteMap(params.RobotID, params.MapName, c.GetString("username"))
	} else {
		err = robot.DeleteMapCMD(params.RobotID, params.MapName, c.GetString("username"))
	}
	response.JSON(c, nil, err)
}

// SetCollectMode 进入地图采集模式
func (Map) SetCollectMode(c *gin.Context) {
	var params struct {
		RobotID string `json:"robot_id"`
		MapName string `json:"map_name"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	var err error
	if helper.CompareVersion("V", c.GetString("device_firmware_version"), "V1.65", "") == 2 {
		err = robot.WildmsgSetCollectMode2Client(params.RobotID, params.MapName, c.GetString("username"))
	} else {
		err = robot.SetCollectMode2ClientCMDPack(params.RobotID, params.MapName, c.GetString("username"))
	}
	response.JSON(c, nil, err)
}

// DetectLoop 回路检测
func (Map) DetectLoop(c *gin.Context) {
	var params struct {
		RobotID string `json:"robot_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	cmdName := "reqDetectLoop"
	// 检测繁忙
	if err := cmd.ISBusy(params.RobotID, cmdName, "95"); err != nil {
		response.JSON(c, nil, err)
		return
	}
	var (
		err  error
		stat int32
	)
	stat, err = robot.ReqDetectLoopCMDPack(params.RobotID)
	if err == nil {
		response.JSON(c, map[string]interface{}{
			"loop_stat": stat,
		}, nil)
		return
	}
	response.JSON(c, nil, errorx.New("未知错误", -1))
}

// SetCollectModeFinish 完成地图采集
func (Map) SetCollectModeFinish(c *gin.Context) {
	var params struct {
		RobotID string `json:"robot_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	var err error
	if helper.CompareVersion("V", c.GetString("device_firmware_version"), "V1.65", "") == 2 {
		err = robot.WildmsgCollectModeFinish(params.RobotID, c.GetString("username"))
	} else {
		err = robot.SetCollectModeFinish2ClientCMCPack(params.RobotID, c.GetString("username"))
	}

	response.JSON(c, nil, err)
}

// MapEx 获取地图扩展数据
func (Map) MapEx(c *gin.Context) {
	if c.Query("robot_id") == "" {
		response.JSON(c, nil, errorx.New("机器id不能为空", -1))
		return
	}
	if c.Query("map_name") == "" {
		response.JSON(c, nil, errorx.New("地图名称不能为空", -1))
		return
	}
	var m models.DeviceMap
	rowsAffected := mysql.NewDB().Model(&models.DeviceMap{}).
		Where("map_name = ?", c.Query("map_name")).
		Where("robot_id = ?", c.Query("robot_id")).
		Where("deleted_at = ?", 0).
		Take(&m).RowsAffected
	if rowsAffected <= 0 {
		response.JSON(c, "", nil)
		return
	}
	mapExtData, err := file.ReadMapFile(config.Config.FileSaveDir, path.Join(c.Query("robot_id"), m.MapExMd5)+".ext")
	if err != nil {
		response.JSON(c, nil, errorx.New("扩展md5值不能为空", -1))
		return
	}
	response.JSON(c, base64.StdEncoding.EncodeToString(mapExtData), nil)
}
